package com.stud.common.utils.poi;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.afterturn.easypoi.word.WordExportUtil;
import cn.afterturn.easypoi.word.entity.MyXWPFDocument;
import com.aspose.cells.*;
import com.google.common.collect.Maps;
import com.stud.common.constant.Constants;
import com.stud.common.exception.ServiceException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.util.IOUtils;
import org.springframework.core.io.ClassPathResource;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

/**
 * @author sdx
 * @title
 * @desription
 * @data 2022-12-10 10:53
 */
@Slf4j
public class EasyPoiUtil {
    /**
     * 模板：导出word
     *
     * @param is        模板流，放在、resources/template下
     * @param paramsMap {{参数}}
     * @param response  web 响应
     */
    public static void exportWordTemplate(InputStream is, Map<String, Object> paramsMap, HttpServletResponse response) {
        String fileName = paramsMap.getOrDefault("fileName", "exportWord").toString() + ".docx";
        try {
            // 文件名
            MyXWPFDocument doc = new MyXWPFDocument(is);
            WordExportUtil.exportWord07(doc, paramsMap);
            // 设置响应体内容类型
            response.setContentType("application/octet-stream");
            // 添加响应头
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            // 暴露新添加的响应头
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            //将word文档流输出到输出流中
            doc.write(response.getOutputStream());
            //关闭流
            doc.close();
        } catch (Exception e) {
            e.printStackTrace();
            log.info(e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * 模板：导出excel
     *
     * @param is        模板流，放在、resources/template下
     * @param paramsMap {{参数}}
     * @param response  web响应
     * @param excelType excel类型  xls / xlsx
     */
    public static void exportExcelTemplate(InputStream is, Map<String, Object> paramsMap, HttpServletResponse response, HttpServletRequest request, String excelType) {
        // 文件名
        String fileName = paramsMap.getOrDefault("fileName", "exportExcel").toString() + excelType;
        try {
            TemplateExportParams params = new TemplateExportParams();
            Workbook workbook = WorkbookFactory.create(is);
            params.setTemplateWb(workbook);
            Workbook book = ExcelExportUtil.exportExcel(params, paramsMap);
            downLoadExcel(fileName, response, request, book);
        } catch (Exception e) {
            e.printStackTrace();
            log.info(e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * 根据excel模版导出分页PDF
     *
     * @param templateName   模版名称
     * @param fileName       导出的文件名称(最终导出名称看前端处理)
     * @param transverse     是否横版
     * @param paramsMap      每页都一样的的通用参数
     * @param data           每页都不一样的分页数据
     * @param otherParamList 每页都不一样的扩展参数,长度必须和data长度保持一致,也可以为null;比如计算某一列之和需要用到
     * @param response
     * @param request
     * @param <T>
     */
    public static <T> void exportExcelTemplate2PDF(String templateName, String fileName, boolean transverse, Map<String, Object> paramsMap, List<List<T>> data, List<Map> otherParamList, HttpServletRequest request, HttpServletResponse response) {
        ClassPathResource classPathResource = new ClassPathResource("template/" + templateName);
        Workbook book = null;
        com.aspose.cells.Workbook asposeBook = null;
        try (Workbook workbook = WorkbookFactory.create(classPathResource.getInputStream())) {
            TemplateExportParams templateExportParams = new TemplateExportParams("template/" + templateName);
            templateExportParams.setTemplateWb(workbook);

            Map<Integer, List<Map<String, Object>>> params = new HashMap<>();

            for (int i = 0; i < data.size(); i++) {
                int page = i + 1;
                List<T> tempList = data.get(i);
                List<Map<String, Object>> mapList = new ArrayList<>();
                Map<String, Object> tempParamsMap = Maps.newHashMap(paramsMap);

                if (Objects.nonNull(otherParamList)) {
                    tempParamsMap.putAll(otherParamList.get(i));
                }

                tempParamsMap.put("sheetName", "第" + page + "页");
                tempParamsMap.put("list", tempList);
                mapList.add(tempParamsMap);
                params.put(i, mapList);
            }

            book = ExcelExportUtil.exportExcelClone(params, templateExportParams);

            String filePath = "/home/temp" + UUID.randomUUID();
            FileOutputStream fos = new FileOutputStream(filePath);
            book.write(fos);

//            解决linux系统下或docker环境缺少中文字体导致的中文乱码,把windows系统中的C:/Windows/Fonts下的字体拷贝到对应文件夹下就可以
//            IndividualFontConfigs configs = new IndividualFontConfigs();
//            configs.setFontFolder("/home/fonts/chinese", true);
//            LoadOptions loadOptions = new LoadOptions();
//            loadOptions.setFontConfigs(configs);
//            asposeBook = new com.aspose.cells.Workbook(Files.newInputStream(Paths.get(filePath)),loadOptions);

            asposeBook = new com.aspose.cells.Workbook(Files.newInputStream(Paths.get(filePath)));

            WorksheetCollection worksheets = asposeBook.getWorksheets();

            worksheets.forEach(o -> {
                Worksheet worksheet = (Worksheet) o;
                PageSetup pageSetup = worksheet.getPageSetup();
                if (transverse) {
                    pageSetup.setOrientation(PageOrientationType.LANDSCAPE);
                }
                pageSetup.setCenterVertically(true);
                pageSetup.setCenterHorizontally(true);
                pageSetup.setLeftMargin(0D);
                pageSetup.setRightMargin(0D);
            });

            response.setCharacterEncoding(request.getCharacterEncoding());
            response.setHeader("content-Type", "application/pdf");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            asposeBook.save(response.getOutputStream(), SaveFormat.PDF);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (book != null) {
                try {
                    book.close();
                } catch (IOException ignored) {

                }
            }
        }
    }

    /**
     * excel下载
     *
     * @param fileName 下载时的文件名称
     * @param response
     * @param workbook excel数据
     */
    public static void downLoadExcel(String fileName, HttpServletResponse response, HttpServletRequest request, Workbook workbook) throws IOException {
        try {
            fileName = fileName.contains("xls") ? fileName : fileName + ".xlsx";
            response.setCharacterEncoding(request.getCharacterEncoding());
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, Constants.UTF8));
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

    /**
     * EASY-POI 导出
     *
     * @param field2Labels
     * @param list
     * @param response
     */
    public static void exportExcel(List<ExcelExportEntity> field2Labels, ExportParams exportParams, List list, HttpServletResponse response) {
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, field2Labels, list);
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        try {
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            log.error("导出Excel异常{}", e.getMessage());
        } finally {
            IOUtils.closeQuietly(workbook);
        }

    }

    /**
     * EASY-POI 导出
     *
     * @param field2Labels
     * @param list
     * @param response
     */
    public static void exportExcel(List<ExcelExportEntity> field2Labels, List list, HttpServletResponse response) {
        exportExcel(field2Labels, ExportParamsFactory.buildDefault(), list, response);
    }

    /**
     * 模板：导出word
     *
     * @param template  模板，放在、resources/template下
     * @param paramsMap {{参数}}
     * @param response  web 响应
     */
    public void exportWordTemplate(String template, Map<String, Object> paramsMap, HttpServletResponse response) {
        InputStream is = this.getClass().getResourceAsStream(template);
        exportWordTemplate(is, paramsMap, response);
    }
}
